package me.yuzho.study.javaweb;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** 使用线程池 + 限制等待队列 实现WEB服务器
 * @author yzhou-citrix
 *
 */
public class ThreadPoolLimitPool {
    
    private static final Logger log = LoggerFactory.getLogger(ThreadPoolLimitPool.class);
    
    final static String response =
            "HTTP/1.0 200 OK\r\n" +
            "Content-type: text/plain\r\n" +
            "\r\n" +
            "Hello World\r\n";
    
    public static void handleRequest(Socket socket) throws IOException {
        // Read the input stream, and return "200 OK"
        try {
          BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
          log.info(in.readLine());
          log.info("Handle request in thread: " + Thread.currentThread().getName());
          OutputStream out = socket.getOutputStream();
          out.write(response.getBytes(StandardCharsets.UTF_8));
        } finally {
          socket.close();
        }
    }

    public static ExecutorService newBoundedFixedThreadPool(int nThreads, int capacity) {
        
        return new ThreadPoolExecutor(nThreads, nThreads, 
                0L, TimeUnit.MILLISECONDS, 
                new LinkedBlockingQueue<Runnable>(capacity),
                new ThreadPoolExecutor.DiscardPolicy());
        
    }
    
    public static void main(String[] args) {
        ServerSocket listener = null;
        try {
            
            ExecutorService executor  = newBoundedFixedThreadPool(4, 16);
            
            listener = new ServerSocket(8080);
            log.info("Server started.");
            
            while (true) {
                Socket socket = listener.accept();
                executor.submit(() -> {
                    try {
                        handleRequest(socket);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(listener != null) {
                try {
                    listener.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
